package com.axend.aerosense.network.websocket;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

import com.axend.aerosense.base.utils.ThreadPoolUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ThreadUtils;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;

public class JWebSocketClient extends WebSocketClient{

    private IConnectAfterRun iConnectAfterRun;
    private IOnMessage iOnMessage;
    private IOnError iOnError;
    private boolean closeByUser = false;
    private boolean reconnect = false;

    public boolean isReconnect(){
        return reconnect;
    }

    public JWebSocketClient(Builder builder){
        super(builder.uri);
        this.iOnMessage = builder.iOnMessage;
        this.iConnectAfterRun = builder.iConnectAfterRun;
        this.iOnError = builder.iOnError;
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        LogUtils.d("JWebSClient", "onOpen---> connection");
        reconnect = false;
    }

    @Override
    public void onMessage(String message) {
        LogUtils.d("JWebSClient", message);
        if(null != iOnMessage){
            iOnMessage.onMessage(message);
        }
    }
    public synchronized void jReconnect(){
        if(reconnect){
            return;
        }
        reconnect = true;
        LogUtils.d("JWebSClient", "jReconnect");
        ThreadPoolUtils.getInstance().execute(()->{
            try {
                Thread.sleep(2000); // 防止线程池耗尽，导致无法创建线程报错
                JWebSocketClient.this.reconnect(); // 此处内涵线程创建
            } catch (InterruptedException e) {
                e.printStackTrace();
                LogUtils.d("JWebSClient-Socket", "threadpool full, can't create thread!");
            }
        });
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        reconnect = false;
        LogUtils.e("JWebSClient", "onClose");
        if(!closeByUser){
            // 生命周期控制，没有意外断开自动重连
            jReconnect();

        }else {
            LogUtils.e("JWebSClient", "用户主动断开");
            // 用户主动断开
            closeByUser = false;
        }
    }

    @Override
    public void onError(Exception ex) {
        reconnect = false;
        ex.printStackTrace();
        LogUtils.e("JWebSClient", "onError",ex.toString());
        if(null != iOnError){
            iOnError.onError(ex);
        }
    }

    public void jConnect() {
        try {
            LogUtils.e("JWebSClient", "jConnect");
            connectBlocking();
            LogUtils.d("JWebSClientConnectBlock", "connection success", getURI().toString());
            if (isOpen()) {
                if (null != iConnectAfterRun) {
                    iConnectAfterRun.run();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void closeConnect() {
        try {
            close();
            LogUtils.d("JWebSClient-Socket", "closed");
        } catch (Exception e) {
            e.printStackTrace();
            LogUtils.d("JWebSClient-Socket", "close by Exception");
        }
    }

    /**
     * 由用户关闭, 将会终止重试
     */
    public void closeConnectByUser() {
        LogUtils.e("JWebSClient", "closeConnectByUser");
        closeByUser = true;
        closeConnect();
    }

    /**
     * 发送消息
     */
    public void jSendMsg(String msg) {
        this.send(msg);
        LogUtils.d("JWebSClient-sendmessage", msg);
    }

    public interface IConnectAfterRun {
        void run();
    }

    public interface IOnMessage {
        void onMessage(String message);
    }

    public interface IOnError {
        void onError(Exception e);
    }

    public static class Builder{
        private URI uri;
        private IConnectAfterRun iConnectAfterRun;
        private IOnMessage iOnMessage;
        private IOnError iOnError;

        public Builder(URI uri, IOnMessage iOnMessage){
            this.uri = uri;
            this.iOnMessage = iOnMessage;
        }
        public Builder connectAfterRun(IConnectAfterRun connectAfterRun){
            this.iConnectAfterRun = connectAfterRun;
            return this;
        }

        public Builder onError(IOnError iOnError){
            this.iOnError = iOnError;
            return this;
        }

        public JWebSocketClient builder(){
            return new JWebSocketClient(this);
        }
    }

}